package icu.qx.common.utils;

import com.ruoyi.common.core.domain.R;
import icu.qx.common.feign.SysCodeFeign;
import icu.qx.common.pojo.SysCode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

@Component
public class CodeUtils {

    @Autowired
    private SysCodeFeign sysCodeFeign;

    private final Lock lock = new ReentrantLock();

    /**
     * 生成主键
     */
    public String generateCode(String tableName) {
        lock.lock();
        try {
            // 通过名字得到表所有的信息
            R<SysCode> result = sysCodeFeign.getInfoByCodeTableName(tableName);
            if (result.getCode() != 200) {
                return "";
            }
            SysCode sysCode = result.getData();
            // 时间规则
            Character codeTimeRule = sysCode.getCodeTimeRule();
            // 通过 char 返回 规则
            String timeRule = getTimeRuleByChar(codeTimeRule);
            // 通过规则返回时间
            String time = getTime(timeRule);
            String lastCode = getCode(sysCode);
            // 编码加上 step
            editSysCode(sysCode, sysCode.getCodeCurrNum(), sysCode.getCodeStep());
            return sysCode.getCodePrefix() + time + lastCode;
        } finally {
            lock.unlock();
        }
    }

    /**
     * code 增加 step
     */
    private void editSysCode(SysCode sysCode, Integer currNum, Integer step) {
        currNum = currNum + step;
        sysCode.setCodeCurrNum(currNum);
        sysCodeFeign.edit(sysCode);
    }

    /**
     * 通过时间规则，返回时间
     */
    private String getTime(String timeRule) {
        // 创建一个SimpleDateFormat对象，指定日期格式
        SimpleDateFormat sdf = new SimpleDateFormat(timeRule);
        // 获取当前日期时间
        Date date = new Date();
        // 使用SimpleDateFormat格式化日期
        return sdf.format(date);
    }

    /**
     * 通过时间类型返回时间规则
     */
    private String getTimeRuleByChar(Character codeTimeRule) {
        if (codeTimeRule == '1') {
            return "yyyyMM";
        } else if (codeTimeRule == '2') {
            return "yyyyMMddHHmm";
        } else {
            return "yyyyMMdd";
        }
    }

    /**
     * 生成指定长度的数字
     */
    private String getCode(SysCode sysCode) {
        if (sysCode.getCodeGenerateType() == '0') {
            return getCodeByDay(sysCode);
        }
        return getCodeByStep(sysCode.getCodeCurrNum(), sysCode.getCodeStep(), sysCode.getCodeLength(), sysCode.getCodePad());
    }

    /**
     * 每日自动生成code
     */
    private String getCodeByDay(SysCode sysCode) {
        Boolean flag = isSameTimeBySliceTime(sysCode);
        if (!flag) {
            sysCode.setCodeCurrNum(0);
        }
        return getCodeByStep(sysCode.getCodeCurrNum(), sysCode.getCodeStep(), sysCode.getCodeLength(), sysCode.getCodePad());
    }

    /**
     * 截取预览中编码的时间 判断是否相同
     */
    private Boolean isSameTimeBySliceTime(SysCode sysCode) {
        String timeRule = getTimeRuleByChar(sysCode.getCodeGenerateType());
        String oldTime = sysCode.getCodePreview().substring(sysCode.getCodePrefix().length(), sysCode.getCodePrefix().length() + timeRule.length());
        String newTime = getTime(timeRule);
        if (newTime.equals(oldTime)) {
            return true;
        }
        sysCode.setCodePreview(sysCode.getCodePreview().replace(oldTime, newTime));
        return false;
    }

    /**
     * 递增生成code
     */
    private String getCodeByStep(Integer currNum, Integer step, Integer length, Character pad) {
        StringBuilder code = new StringBuilder();
        String lastNum = currNum + step + "";
        for (int i = 0; i < length - lastNum.length(); i++) {
            code.append(pad);
        }
        return code + lastNum;
    }
}
